package io.renren.controller;

import io.renren.annotation.Login;
import io.renren.common.exception.RRException;
import io.renren.common.utils.ConfigConstant;
import io.renren.common.utils.DateUtils;
import io.renren.common.utils.HttpClientUtils;
import io.renren.common.utils.HttpContextUtils;
import io.renren.common.utils.IPUtils;
import io.renren.common.utils.ProjectConstant;
import io.renren.common.utils.R;
import io.renren.common.utils.RedisUtils;
import io.renren.common.utils.SMSManages;
import io.renren.common.utils.SpringContextUtils;
import io.renren.common.validator.Assert;
import io.renren.entity.MemberEntity;
import io.renren.entity.PhoneCodeEntity;
import io.renren.entity.RecDownloadEntity;
import io.renren.service.MemberService;
import io.renren.service.PhoneCodeService;
import io.renren.service.RecDownloadService;
import io.renren.service.SysConfigService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;

import java.util.Date;

import org.apache.commons.lang.RandomStringUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.mapper.EntityWrapper;

/**
 * 注册接口
 * 
 * @author chenshun
 * @email sunlightcs@gmail.com
 * @date 2017-03-26 17:27
 */
@RestController
@RequestMapping("/api/send")
@Api(tags = "短信接口")
public class ApiPhoneCodeController extends AbstractController {

	@Autowired
	MemberService memberService;

	@Autowired
	PhoneCodeService phoneCodeService;

	@Autowired
	SysConfigService sysConfigService;

	@Autowired
	RecDownloadService recDownloadService;

	@Autowired
	RedisUtils redisUtils;

	private void send(String mobile, int type) {

		Assert.isNull(redisUtils.get("SEND_MSG_" + IPUtils.getIpAddr(HttpContextUtils.getHttpServletRequest())), "发送验证码过于频繁");

		Date now = new Date();

		String captcha = RandomStringUtils.randomNumeric(4);
		/*********** 发送短信验证 **********/
		SMSManages sms = new SMSManages(sysConfigService.getValue(ConfigConstant.SMS_USER), sysConfigService.getValue(ConfigConstant.SMS_PWD), sysConfigService.getValue(ConfigConstant.SMS_VERY_CODE));
		String retCode = sms.sendSMS(mobile, "JSM42425-0005", "@1@=" + captcha);
		logger.info("retCode：" + retCode);
		Assert.isTrue(retCode.indexOf("<status>0</status>") != -1, "短信发送失败");

		// 保存数据库
		PhoneCodeEntity phoneCode = new PhoneCodeEntity();
		phoneCode.setCaptcha(captcha);
		phoneCode.setMobile(mobile);
		phoneCode.setType(type);
		phoneCode.setExpireTime(DateUtils.addDateMinutes(now, 5));// 5分钟
		phoneCode.setCreateTime(now);
		phoneCodeService.insert(phoneCode);

		// 限制此IP发送验证码频率
		redisUtils.set("SEND_MSG_" + IPUtils.getIpAddr(HttpContextUtils.getHttpServletRequest()), "YES", 60);
	}

	public static void checkCaptcha(String mobile, String captcha, int type) {
		// 避免攻击者频繁试验证码
		RedisUtils redisUtils = SpringContextUtils.getBean(RedisUtils.class);
		String count = redisUtils.get("CHECK_" + type + "_" + mobile);
		int maxCount = 0;
		if (StringUtils.isNotBlank(count)) {
			maxCount = Integer.parseInt(count) + 1;
		}
		if (maxCount >= 10) {
			System.out.println("type:" + type + ",多次输错验证码:" + mobile);
			throw new RRException("多次尝试验证码错误被系统禁止");
		} else {
			redisUtils.set("CHECK_" + type + "_" + mobile, maxCount, 3600);
		}
		PhoneCodeService phoneCodeService = SpringContextUtils.getBean("phoneCodeService", PhoneCodeService.class);
		PhoneCodeEntity phoneCode = phoneCodeService.selectOne(new EntityWrapper<PhoneCodeEntity>().eq("mobile", mobile).eq("captcha", captcha).eq("type", type).orderBy("create_time", false));
		if (phoneCode == null || phoneCode.getExpireTime().getTime() < System.currentTimeMillis()) {
			throw new RRException("验证码无效");
		}
		// 使验证码过期
		phoneCodeService.deleteById(phoneCode.getId());
	}

	public static boolean toTencent(String ticket, String randstr) {
		try {
			SysConfigService config = SpringContextUtils.getBean("sysConfigService", SysConfigService.class);
			String params = "aid=" + config.getValue(ConfigConstant.TENCENT_AID) + "&AppSecretKey=" + config.getValue(ConfigConstant.TENCENT_APP_SECRET_KEY) + "&Ticket=" + ticket + "&Randstr=" + randstr + "&UserIP=" + IPUtils.getIpAddr(HttpContextUtils.getHttpServletRequest());
			String text = HttpClientUtils.sendHttpPost(ConfigConstant.TENCENT_CAPTCHA_URL, params);
			System.out.println("tencent response:" + text);
			int response = JSON.parseObject(text).getInteger("response");
			if (response == 1) {
				return true;
			}
		} catch (Exception e) {
			e.printStackTrace();
		}

		return false;
	}

	@PostMapping("login")
	@ApiOperation("发送登录验证码")
	public R login(@RequestParam String mobile, @RequestParam String ticket, @RequestParam String randstr) {
		Assert.hasText(mobile, "手机号无效");
		Assert.hasText(ticket, "参数有误");
		Assert.hasText(randstr, "参数有误");
		Assert.isTrue(toTencent(ticket, randstr), "验证失败");
		send(mobile, ProjectConstant.PHONECODE_TYPE_LOGIN);
		return R.ok();
	}

	@Login
	@PostMapping("bind")
	@ApiOperation("发送绑定手机验证码")
	public R bind(@RequestParam String mobile, @RequestParam String ticket, @RequestParam String randstr) {
		Assert.hasText(mobile, "手机号无效");
		Assert.hasText(ticket, "参数有误");
		Assert.hasText(randstr, "参数有误");
		Assert.isTrue(toTencent(ticket, randstr), "验证失败");
		Assert.isTrue(memberService.selectCount(new EntityWrapper<MemberEntity>().eq("mobile", mobile)) == 0, "手机已存在");
		send(mobile, ProjectConstant.PHONECODE_TYPE_BIND);
		RecDownloadEntity rec = recDownloadService.selectOne(new EntityWrapper<RecDownloadEntity>().eq("mobile", mobile));
		String recPerson = null;
		if (rec != null) {
			recPerson = rec.getRecPerson();
		}
		return R.ok().put("recPerson", recPerson);
	}
}
